/*
 * JTalkerClientChatWindow.java
 *
 * Created on 22. Dezember 2005, 11:25
 */

package com.jtalker.client;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.swing.Action;
import javax.swing.ActionMap;
import javax.swing.BorderFactory;
import javax.swing.ComponentInputMap;
import javax.swing.ImageIcon;
import javax.swing.InputMap;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JToolBar;
import javax.swing.KeyStroke;
import javax.swing.ListModel;
import javax.swing.SwingUtilities;
import javax.swing.border.BevelBorder;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;
import javax.swing.event.ListDataEvent;
import javax.swing.event.ListDataListener;
import javax.swing.plaf.ActionMapUIResource;

import com.jtalker.client.JTalkerClient.MemberData;

/**
 * 
 * @author chrmac@gmx.de
 */
public class JTalkerFrontChat extends JFrame implements Action,
		JTalkerClientCommandInterface {
	private static final long serialVersionUID = 1L;
	private JTalkerClientFront parentClientFront = null;
	/** 聊天对象 */
	private MemberData memberData = null;
	private UpdateTimer ut = null;
	/** List of Strings */
	private ArrayList<String> historyList = new ArrayList<String>();
	private int historyPosition = 0; // 0: last input
	private static final String ownMessageMarker = "<<<<<ME>>>>>";
	private int textAreaStyle = 0; // How to format the messages?
	private MemberListModel memberListModel = null; // Chat-room users Model for JList
	private String[] chatRoomUsers = { "Loading..." }; // TODO: Fill this array!
	private boolean isChatRoom = false;

	/** C'tor */
	public JTalkerFrontChat(JTalkerClientFront parent, MemberData member) {
		this.parentClientFront = parent;
		this.memberData = member;
		this.initComponents();
		this.initShortcuts();
		this.jTextAreaInput.requestFocus();
		if (this.memberData.type.equals(JTalkerParser.USER_TYPE_CHATROOM)) {
			try {
				this.isChatRoom = true;
				this.textAreaStyle = 1;
				this.memberListModel = new MemberListModel();
				this.jListMsg.setModel(this.memberListModel);
				this.jPanelMsgArea.setVisible(true);
				this.jLabelStatus.setText("Chatroom: " + member.short_name + " @ "
						+ member.ip);
			} catch (Exception e) {
				e.printStackTrace();
			}
		} else {
			this.jPanelMsgArea.setVisible(false);
			this.jLabelStatus.setText("Chat with " + member.short_name + " @ "
					+ member.ip);
		}
		this.setLocationRelativeTo(null);
		this.setTitle(member.short_name);
		this.parentClientFront.theClient.registerForCommandResponse(this);

		// Init Timer for updating the Chat-Window
		ut = new UpdateTimer(this);
		ut.start();

		// Overwrite text and background colors
		this.jEditorPaneDisplayMsg.setBackground(Color
				.decode(parent.theClient.guiBgColor));
		this.jEditorPaneDisplayMsg.setForeground(Color
				.decode(parent.theClient.guiTextColor));
	}

	public void actionPerformed(ActionEvent e) {
		this.sendMessage();
	}

	/**
	 * This method is called from within the constructor to initialize the form.
	 * WARNING: Do NOT modify this code. The content of this method is always
	 * regenerated by the Form Editor.
	 */
	// <editor-fold defaultstate="collapsed"
	// desc=" Generated Code ">//GEN-BEGIN:initComponents
	private void initComponents() {
		jToolBar = new JToolBar();
		jButtonSendMsg = new JButton();
		jButtonSendFile = new JButton();
		jButtonClearHistory = new JButton();
		jButtonView = new JButton();
		jPanelWhole = new JPanel();
		jPanelTalkAreaSouth = new JPanel();
		jLabelStatus = new JLabel();
		jPanelHistory = new JPanel();
		jButtonHistoryUp = new JButton();
		jButtonHistoryDown = new JButton();
		jScrollPaneTextArea = new JScrollPane();
		jTextAreaInput = new JTextArea();
		// jTextAreaInput = new JEditorPane("text/plain", "");
		jPanelMsgArea = new JPanel();
		jScrollPaneMsgArea = new JScrollPane();
		jListMsg = new JList();
		jScrollPane1 = new JScrollPane();
		jEditorPaneDisplayMsg = new JEditorPane("text/html; charset=UTF-8", null);
		jEditorPaneDisplayMsg.setEditable(false);
		ClassLoader cl = ResourceAnchor.class.getClassLoader();

		this.addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent evt) {
				exitForm(evt);
			}
		});

		jEditorPaneDisplayMsg.addHyperlinkListener(new HyperlinkListener() {
			public void hyperlinkUpdate(HyperlinkEvent evt) {
				hyperlinkUpdateEvent(evt);
			}
		});

		// Plain buttons
		jToolBar.setRollover(true);

		jButtonSendMsg.setText("Send Msg.");
		jButtonSendMsg.setIcon(new ImageIcon(cl.getResource("com/jtalker/rs/icons/mail_send.png")));
		jButtonSendMsg.setToolTipText("Send message now (Ctrl+ENTER)");
		jButtonSendMsg.setMargin(new Insets(1, 2, 1, 2));
		jButtonSendMsg.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent evt) {
				sendMessage();
			}
		});
		jToolBar.add(jButtonSendMsg);

		jButtonSendFile.setText("Send File");
		jButtonSendFile.setIcon(new ImageIcon(cl.getResource("com/jtalker/rs/icons/file_send.png")));
		jButtonSendFile.setToolTipText("Send File");
		jButtonSendFile.setMargin(new Insets(1, 2, 1, 2));
		jButtonSendFile.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent evt) {
				sendFile();
			}
		});
		jToolBar.add(jButtonSendFile);
		jToolBar.addSeparator();

		jButtonClearHistory.setIcon(new ImageIcon(cl.getResource("com/jtalker/rs/icons/editdelete.png")));
		jButtonClearHistory.setToolTipText("Clear history");
		jButtonClearHistory.setMargin(new Insets(1, 2, 1, 2));
		jButtonClearHistory.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent evt) {
				clearHistory();
			}
		});
		jToolBar.add(jButtonClearHistory);

		jButtonView.setIcon(new ImageIcon(cl.getResource("com/jtalker/rs/icons/toggle_view.png")));
		jButtonView.setToolTipText("Toggle View");
		jButtonView.setMargin(new Insets(1, 2, 1, 2));
		jButtonView.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent evt) {
				toggleView();
			}
		});

		jToolBar.add(jButtonView);

		this.getContentPane().add(jToolBar, BorderLayout.NORTH);

		jPanelWhole.setLayout(new BorderLayout());

		jPanelWhole.setBackground(new Color(102, 102, 102));
		jPanelTalkAreaSouth.setLayout(new BorderLayout());
		jPanelTalkAreaSouth.setPreferredSize(new Dimension(400, 85));
		
		jLabelStatus.setText("Status");
		jLabelStatus.setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED));
		jPanelTalkAreaSouth.add(jLabelStatus, BorderLayout.SOUTH);

		jPanelHistory.setLayout(new GridLayout(2, 1));
		jPanelHistory.setPreferredSize(new Dimension(50, 100));

		jButtonHistoryUp.setIcon(new ImageIcon(cl.getResource("com/jtalker/rs/icons/uparrow.png")));
		jButtonHistoryUp.setMargin(new Insets(0, 0, 0, 0));
		jButtonHistoryUp.setToolTipText("History Up");
		jButtonHistoryUp.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent evt) {
				historyUp();
			}
		});
		jPanelHistory.add(jButtonHistoryUp);

		jButtonHistoryDown.setIcon(new ImageIcon(cl.getResource("com/jtalker/rs/icons/downarrow.png")));
		jButtonHistoryDown.setMargin(new Insets(0, 0, 0, 0));
		jButtonHistoryDown.setToolTipText("History Down");
		jButtonHistoryDown.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent evt) {
				historyDown();
			}
		});
		jPanelHistory.add(jButtonHistoryDown);

		jPanelTalkAreaSouth.add(jPanelHistory, BorderLayout.EAST);

		jTextAreaInput.setMinimumSize(new Dimension(20, 20));
		jTextAreaInput.setPreferredSize(new Dimension(100, 20));
		// jTextAreaInput.setColumns(5);
		jTextAreaInput.setLineWrap(true);
		// jTextAreaInput.setRows(2);
		jTextAreaInput.setToolTipText("Enter your message here!");
		jTextAreaInput.setWrapStyleWord(true);
		jScrollPaneTextArea.setViewportView(jTextAreaInput);

		jPanelTalkAreaSouth.add(jScrollPaneTextArea, BorderLayout.CENTER);
		jPanelWhole.add(jPanelTalkAreaSouth, BorderLayout.SOUTH);
		jPanelMsgArea.setLayout(new BorderLayout());
		jScrollPaneMsgArea.setViewportView(jListMsg);
		jPanelMsgArea.add(jScrollPaneMsgArea, BorderLayout.CENTER);
		jPanelWhole.add(jPanelMsgArea, BorderLayout.EAST);
		jScrollPane1.setViewportView(jEditorPaneDisplayMsg);
		jPanelWhole.add(jScrollPane1, BorderLayout.CENTER);

		this.getContentPane().add(jPanelWhole, BorderLayout.CENTER);
		pack();

		// Init smiles
		url_smiles_smile = cl.getResource("com/jtalker/rs/icons/smiles/smile.png");
		url_smiles_wink = cl.getResource("com/jtalker/rs/icons/smiles/wink.png");
		url_smiles_unhappy = cl.getResource("com/jtalker/rs/icons/smiles/unhappy.png");
		url_smiles_oh = cl.getResource("com/jtalker/rs/icons/smiles/oh.png");
		url_smiles_tongue = cl.getResource("com/jtalker/rs/icons/smiles/tongue.png");
		url_smiles_biggrin = cl.getResource("com/jtalker/rs/icons/smiles/biggrin.png");
	}// </editor-fold>//GEN-END:initComponents

	// ############################## METHODS
	// ##############################################

	/** Gets clicked URL and calls Browser */
	private void hyperlinkUpdateEvent(HyperlinkEvent evt) {
		if (evt.getEventType() == HyperlinkEvent.EventType.ACTIVATED)
			this.parentClientFront.openBrowser(evt.getDescription());
	}

	/** Clears the history */
	private void clearHistory() {
		this.memberData.clearMessages();
		this.jEditorPaneDisplayMsg.setText("");
	}

	/** Starts the send-file procedure */
	private void sendFile() {
		// Check if disconnected
		if (!this.memberData.isConnected()) {
			JOptionPane.showMessageDialog(this,
					"The User is offline - you can't send a file!",
					"User is offline", JOptionPane.INFORMATION_MESSAGE);
			return;
		}

		BASE64Handler b64h = new BASE64Handler(this);
		BASE64Handler.EncodedFileObject efo = b64h.getEncodedFile();

		if (efo != null) {
			this.parentClientFront.theClient.sendMessage(efo.data,
					this.memberData.name, "file", efo.filename);
			this.memberData.addMessage(ownMessageMarker + " "
					+ "<i>---Sending File--- (" + efo.filename + ")</i>",
					"Sending File", "normal");
			// this.member.hasNewMessage = false;
			// this.updateWindow();
		} else {
			// Show Error
			JOptionPane.showMessageDialog(this,
					"Can't send file:\n" + b64h.getLastError(),
					"Can't send file", JOptionPane.ERROR_MESSAGE);
		}
	}

	/** Send the message */
	private void sendMessage() {
		// Check if disconnected
		if (!this.memberData.isConnected()) {
			JOptionPane.showMessageDialog(this,
					"The User is offline - you can't send a message!",
					"User is offline", JOptionPane.INFORMATION_MESSAGE);
			return;
		}

		String message = this.jTextAreaInput.getText();

		// Save in History
		this.historyList.add(message);
		this.historyPosition = 0;

		// Replace Whitespace and HTML
		message = message.replaceAll("\n", "<br>");
		message = message.replaceAll("\r", "");
		if (message.length() > 0) {
			if (!this.memberData.type.equals(JTalkerParser.USER_TYPE_CHATROOM)) {
				this.memberData.addMessage(ownMessageMarker + " " + message,
						"my Message", "normal");
			}
			// this.member.hasNewMessage = false;
			// this.updateWindow();
			if (message.startsWith("/")) {
				message = message.replaceFirst("/", "");
				this.parentClientFront.theClient.sendMessage(message,
						this.memberData.name, "command", null);
			} else {
				this.parentClientFront.theClient.sendMessage(message,
						this.memberData.name);
			}
			// Clear editor text
			this.jTextAreaInput.setText("");
		}
	}

	/** Back in the history */
	public void historyUp() {
		int tmpPos = this.historyList.size() - 1 - this.historyPosition;
		if (tmpPos < 0){
			return;
		}
		this.jTextAreaInput.setText(this.historyList.get(tmpPos));
		this.historyPosition++;
		if (this.historyPosition >= this.historyList.size()){
			this.historyPosition--;
		}
	}

	/** Forward in the history */
	public void historyDown() {
		int tmpPos = this.historyList.size() - 1 - this.historyPosition;
		if (tmpPos < 0)
			return;

		this.jTextAreaInput.setText((String) this.historyList.get(tmpPos));
		this.historyPosition--;
		if (this.historyPosition < 0) {
			this.jTextAreaInput.setText("");
			this.historyPosition = 0;
		}
	}

	/** Toggles the styles of view */
	public void toggleView() {
		this.textAreaStyle++;

		if (this.textAreaStyle > 2)
			this.textAreaStyle = 0;

		if (this.textAreaStyle != 2) {
			this.jEditorPaneDisplayMsg.setContentType("text/html; charset=UTF-8");
		} else
			this.jEditorPaneDisplayMsg.setContentType("text/plain");

		this.updateWindow();
	}

	/** Updates the chat window */
	public void updateWindow() {
		String messageLines = "";

		// Overwrite text and background colors
		this.jEditorPaneDisplayMsg.setBackground(Color
				.decode(this.parentClientFront.theClient.guiBgColor));
		this.jEditorPaneDisplayMsg.setForeground(Color
				.decode(this.parentClientFront.theClient.guiTextColor));

		// Update only, if this window is visible!
		if (!this.isVisible()) {
			return;
		}
		// Check for received files
		/*
		 * if(this.member.saveBASE64Files()) {
		 * this.member.addMessage("<i>---File received---</i>", "my Message",
		 * "normal"); this.member.hasNewMessage = false; }
		 */

		// for( int i = this.member.numOfMessages() - 1; i >= 0; i-- ) {
		for (int i = 0; i < this.memberData.numOfMessages(); i++) {
			String tmpMess = this.memberData.getMessage(i);
			// System.out.println("------tmpMess------:" + tmpMess);
			if (tmpMess != null) {
				// Get only Text-messages
				String tmpTime = this.memberData.getDate(i);
				messageLines += this.makeTemplate(this.textAreaStyle,
						this.memberData.short_name, tmpTime, tmpMess);
			}
			this.memberData.hasNewMessage = false;
		}
		// System.out.println("------messageLines------:" + messageLines);
		messageLines = messageLines.replaceAll("<html>", "");
		messageLines = messageLines.replaceAll("</html>", "");

		if (this.textAreaStyle != 2) {
			// Make some replacement for HTML based Views Replace smiles
			messageLines = messageLines.replaceAll(":-\\)", "<img src=\""
					+ this.url_smiles_smile.toString() + "\">");
			messageLines = messageLines.replaceAll(":\\)", "<img src=\""
					+ this.url_smiles_smile.toString() + "\">");
			messageLines = messageLines.replaceAll(";-\\)", "<img src=\""
					+ this.url_smiles_wink.toString() + "\">");
			messageLines = messageLines.replaceAll(";\\)", "<img src=\""
					+ this.url_smiles_wink.toString() + "\">");
			messageLines = messageLines.replaceAll(":-\\(", "<img src=\""
					+ this.url_smiles_unhappy.toString() + "\">");
			messageLines = messageLines.replaceAll(":\\(", "<img src=\""
					+ this.url_smiles_unhappy.toString() + "\">");
			messageLines = messageLines.replaceAll(":-O", "<img src=\""
					+ this.url_smiles_oh.toString() + "\">");
			messageLines = messageLines.replaceAll(":-o", "<img src=\""
					+ this.url_smiles_oh.toString() + "\">");
			messageLines = messageLines.replaceAll(":O", "<img src=\""
					+ this.url_smiles_oh.toString() + "\">");
			messageLines = messageLines.replaceAll(":o", "<img src=\""
					+ this.url_smiles_oh.toString() + "\">");
			messageLines = messageLines.replaceAll(":-P", "<img src=\""
					+ this.url_smiles_tongue.toString() + "\">");
			messageLines = messageLines.replaceAll(":-p", "<img src=\""
					+ this.url_smiles_tongue.toString() + "\">");
			messageLines = messageLines.replaceAll(":P", "<img src=\""
					+ this.url_smiles_tongue.toString() + "\">");
			messageLines = messageLines.replaceAll(":p", "<img src=\""
					+ this.url_smiles_tongue.toString() + "\">");
			messageLines = messageLines.replaceAll(":-D", "<img src=\""
					+ this.url_smiles_biggrin.toString() + "\">");
			messageLines = messageLines.replaceAll(":-d", "<img src=\""
					+ this.url_smiles_biggrin.toString() + "\">");
			messageLines = messageLines.replaceAll(":D", "<img src=\""
					+ this.url_smiles_biggrin.toString() + "\">");
			messageLines = messageLines.replaceAll(":d", "<img src=\""
					+ this.url_smiles_biggrin.toString() + "\">");

			// Parse URIs
			try {
				// Replace email addresses
				Pattern p = Pattern
						.compile("[A-Za-z0-9\\.]+\\@[A-Za-z0-9\\.-]+");
				Matcher m = p.matcher(messageLines);
				StringBuffer sb = new StringBuffer();
				boolean wasReplaced = false;
				boolean result = m.find();
				// 过滤邮件名
				while (result) {
					m.appendReplacement(sb, "<a href=\"mailto:" + m.group()
							+ "\">" + m.group() + "</a>");
					wasReplaced = true;
					result = m.find();
				}

				if (wasReplaced) {
					m.appendTail(sb);
					messageLines = sb.toString();
				}

				// Replace URLs
				p = Pattern
						.compile("([^\"])((http://|www\\.)[\\S&&[^<>;:\"]]+)");
				m = p.matcher(messageLines);
				sb = new StringBuffer();
				wasReplaced = false;
				result = m.find();

				while (result) {
					m.appendReplacement(
							sb,
							m.group(1) + "<a href=\"" + m.group(2) + "\">"
									+ m.group(2) + "</a>");
					wasReplaced = true;
					result = m.find();
				}

				if (wasReplaced) {
					m.appendTail(sb);
					messageLines = sb.toString();
				}
			} catch (Exception _e) {
				System.out.println("*** ERROR: while parsing URIs");
			}
		}

		if (messageLines != null) {
			this.jEditorPaneDisplayMsg.setText(messageLines);
		}
		// this.jEditorPaneMain.setCaretPosition(0);
		try {
			int num = this.jEditorPaneDisplayMsg.getDocument().getLength();
			this.jEditorPaneDisplayMsg.setCaretPosition(num);
			if (this.isChatRoom) {
				this.checkChatroomUsers();
			}
		} catch (Exception e) {
		}
	}

	/** Formats the message with a special template */
	private String makeTemplate(int style, String userName, String date,
			String message) {
		String retVal = "";

		if (style == 0) {
			if (!message.startsWith(ownMessageMarker)) {
				retVal += "<table border=\"0\" width=\"100%\"><tr><td bgcolor=\"#cccccc\">"
						+ "<font color=\"black\"><b>"
						+ userName
						+ "</b>"
						+ " ("
						+ date
						+ ")"
						+ "</font></td></tr></table><font color=\""
						+ parentClientFront.theClient.guiTextColor
						+ "\">"
						+ message + "</font><br><br>";
			} else {
				retVal += "<font color=\""
						+ parentClientFront.theClient.guiTextColor
						+ "\">"
						+ message
								.replaceFirst(
										ownMessageMarker,
										"<table border=\"0\" width=\"100%\"><tr><td bgcolor=\"#ffff99\"><font color=\"black\"><b>"
												+ this.parentClientFront.theClient.userName
												+ "</b> ("
												+ date
												+ ")</font></td></tr></table>");
				retVal += "</font><br><br>";
			}
		} else if (style == 1) {
			// Only for Chat-room - no chat-room name
			String tmpUserName = userName;

			if (this.memberData.type.equals(JTalkerParser.USER_TYPE_CHATROOM))
				tmpUserName = "";

			if (!message.startsWith(ownMessageMarker)) {
				retVal += "<font color=\""
						+ parentClientFront.theClient.guiTextColor + "\">"
						+ "<b>(" + date + ") " + tmpUserName + ":</b> "
						+ message + "</font><br>";
			} else {
				if (!this.memberData.type
						.equals(JTalkerParser.USER_TYPE_CHATROOM))
					tmpUserName = this.parentClientFront.theClient.userName;

				retVal += "<font color=\""
						+ parentClientFront.theClient.guiTextColor
						+ "\">"
						+ message.replaceFirst(ownMessageMarker, "<b>("
								+ date + ") " + tmpUserName + ":</b> ");
				retVal += "</font><br>";
			}
		} else if (style == 2) {
			String tmpUserName = userName;

			if (this.memberData.type.equals(JTalkerParser.USER_TYPE_CHATROOM))
				tmpUserName = "";

			if (!message.startsWith(ownMessageMarker)) {
				retVal += "\n(" + date + ") " + tmpUserName + ": " + message;
			} else {
				if (!this.memberData.type
						.equals(JTalkerParser.USER_TYPE_CHATROOM))
					tmpUserName = this.parentClientFront.theClient.userName;

				retVal += message.replaceFirst(ownMessageMarker, "\n(" + date
						+ ") " + tmpUserName + ": ");
			}
		}

		return retVal;
	}

	/** Checks for users in a chatroom */
	private void checkChatroomUsers() {
		if (!this.isChatRoom){
			return;
		}
		this.parentClientFront.theClient.sendMessage("std::getChatRoomUsers(\""
				+ this.memberData.short_name + "\")", null, "command", null,
				"getchatusers01");
	}

	/**
	 * A command answer will be send to us from the server using this method
	 * 
	 * @return true, if we handle this command
	 */
	public boolean setCommandAnswer(String id, String from, String content) {
		if (id.equals("getchatusers01")) {
			String lastResponse = content;

			if (lastResponse == null){
				return true;
			}
			this.chatRoomUsers = lastResponse.split(";;");

			if (this.memberListModel != null){
				this.memberListModel.propertyChanged();
			}
			return true;
		} else if (id.equals("addchatuser01") || id.equals("rmchatuser01")) {
			this.checkChatroomUsers();
			return true;
		}

		return false;
	}

	/** Inits all Keyboard Shortcuts */
	private void initShortcuts() {
		InputMap keyMap = new ComponentInputMap(this.jButtonSendMsg);
		keyMap.put(
				KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, InputEvent.CTRL_MASK),
				"action");

		ActionMap actionMap = new ActionMapUIResource();
		actionMap.put("action", this);

		SwingUtilities.replaceUIActionMap(this.jButtonSendMsg, actionMap);
		SwingUtilities.replaceUIInputMap(this.jButtonSendMsg,
				JComponent.WHEN_IN_FOCUSED_WINDOW, keyMap);
	}

	/** Exit the Application */
	private void exitForm(WindowEvent evt) {
		// this.ucu.terminate = true;
		// this.ut.terminate = true;
		this.dispose();
	}

	// Interface functions for Action
	public Object getValue(String key) {
		return null;
	}

	public void putValue(String key, Object value) {
	}

	// Variables declaration - do not modify//GEN-BEGIN:variables
	private JButton jButtonClearHistory;
	private JButton jButtonHistoryDown;
	private JButton jButtonHistoryUp;
	private JButton jButtonSendFile;
	private JButton jButtonSendMsg;
	private JButton jButtonView;
	private JTextArea jTextAreaInput;
	// private JEditorPane jTextAreaInput;
	private JEditorPane jEditorPaneDisplayMsg;
	private JLabel jLabelStatus;
	private JList jListMsg;
	private JPanel jPanelWhole;
	private JPanel jPanelTalkAreaSouth;
	private JPanel jPanelMsgArea;
	private JPanel jPanelHistory;
	private JScrollPane jScrollPane1;
	private JScrollPane jScrollPaneTextArea;
	private JScrollPane jScrollPaneMsgArea;
	private JToolBar jToolBar;
	// End of variables declaration//GEN-END:variables
	//
	// Smiles
	private java.net.URL url_smiles_smile;
	private java.net.URL url_smiles_wink;
	private java.net.URL url_smiles_unhappy;
	private java.net.URL url_smiles_oh;
	private java.net.URL url_smiles_tongue;
	private java.net.URL url_smiles_biggrin;

	/** Class for asynchron updating the Window */
	public class UpdateTimer extends Thread {
		private JTalkerFrontChat parent = null;
		public boolean terminate = false;

		public UpdateTimer(JTalkerFrontChat parent) {
			this.parent = parent;
		}

		public void run() {
			boolean firstRun = true;
			while (!terminate) {
				try {
					Thread.sleep(300);

					if (firstRun || this.parent.memberData.hasNewMessage) {
						firstRun = false;

						// Check for received files
						if (this.parent.isVisible()) {
							this.parent.updateWindow();

							if (this.parent.memberData.saveBASE64Files()) {
								this.parent.memberData.addMessage(
										"<i>---File received---</i>",
										"my Message", "normal");
							}
						}

					}
				} catch (Exception e) {
				}
			}
		}
	}

	/** Model for the JList with all in a Chatroom */
	// TODO: Implement this in JTalkerMember! or? ;-)
	public class MemberListModel implements ListModel {
		private ListDataListener myDataListener = null;

		// TODO: Replace this by a real size!

		public MemberListModel() {
		}

		// Notify a Change - call this methode if the data-source has changed
		public void propertyChanged() {
			int tmpLength = 0;
			if (chatRoomUsers != null){
				tmpLength = chatRoomUsers.length;
			}
			this.myDataListener.contentsChanged(new ListDataEvent(this,
					ListDataEvent.CONTENTS_CHANGED, tmpLength, 0));
		}

		// List Model Listener
		public void addListDataListener(ListDataListener l) {
			this.myDataListener = l;
		}

		public Object getElementAt(int index) {
			return chatRoomUsers[index];
		}

		public int getSize() {
			if (chatRoomUsers != null){
				return chatRoomUsers.length;
			}else{
				return 0;
			}
		}

		public void removeListDataListener(ListDataListener l) {
		}
	}

}
